package name.weily.liba.views

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.core.view.get
import com.google.android.material.floatingactionbutton.FloatingActionButton
import name.weily.liba.tools.logd


class FloatingActionMenu(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int)
    : ViewGroup(context, attributeSet, defStyleAttr)
    , View.OnClickListener {
    companion object {
        const val VERTICAL = 0
        const val HORIZONTAL = 1
    }

    constructor(context: Context, layout: Int) : this(context, null, 0) {

    }

    private var orientation = HORIZONTAL
    private var padding = 30
    private var gap = 10

    private var isOpen = false
        set(value) {
            field = value
            menuFab.setImageResource(if (value) R.drawable.ic_close_white_24dp else R.drawable.ic_menu_black_36dp)
            refreshMenuItems()
//            invalidate()
        }


    private val menuFab by lazy { FloatingActionButton(getContext()).apply {
        layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        setImageResource(R.drawable.ic_menu_black_36dp)
        isClickable = true
        setOnClickListener { isOpen = !isOpen }
    } }

    constructor(context: Context) : this(context, null, 0)
    constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)

    init {
        addView(menuFab, 0,  menuFab.layoutParams)
    }



    override fun onClick(v: View?) {
        logd("${v?.id}")
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        refreshMenuItems()
    }

    private fun refreshMenuItems() {
        children.forEachIndexed { index, view ->
            if (index > 0) {
                view.visibility = if (isOpen) View.VISIBLE else View.GONE
            }
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        measureChildren(widthMeasureSpec, heightMeasureSpec)

        padding = get(0).measuredWidth / 2

        var wExtra = padding * 2
        var hExtra = padding * 2

        when (orientation) {
            VERTICAL -> {
                measureVertical(widthMeasureSpec, heightMeasureSpec)
                hExtra += (childCount -1)* gap
            }
            HORIZONTAL -> {
                measureHorizontal(widthMeasureSpec, heightMeasureSpec)
                wExtra += (childCount -1)* gap
            }
        }

        setMeasuredDimension(measuredWidth + wExtra, measuredHeight + hExtra)

        logd("measured 2222 width=$measuredWidth, height=$measuredHeight")
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        logd("onlayout $l, $t, $r, $b   w=$measuredWidth h=$measuredHeight")
        when (orientation) {
            VERTICAL -> layoutVertical()
            HORIZONTAL -> layoutHorizontal()
        }
    }

    private fun measureVertical(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val wMode = MeasureSpec.getMode(widthMeasureSpec)
        val hMode = MeasureSpec.getMode(heightMeasureSpec)

        when {
            wMode == MeasureSpec.AT_MOST && hMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(children.map { it.measuredWidth }.max() ?: 0
                    , children.map { it.measuredHeight }.reduce { acc, i -> acc + i})
            }
            wMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(children.map { it.measuredWidth }.max() ?: 0, MeasureSpec.getSize(heightMeasureSpec))
            }
            hMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), children.map { it.measuredHeight }.reduce { acc, i -> acc + i})
            }
        }
    }

    private fun measureHorizontal(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val wMode = MeasureSpec.getMode(widthMeasureSpec)
        val hMode = MeasureSpec.getMode(heightMeasureSpec)

        when {
            wMode == MeasureSpec.AT_MOST && hMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(children.map { it.measuredWidth }.reduce { acc, i -> acc + i }
                    , children.map { it.measuredHeight }.max() ?: 0)
            }
            wMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(children.map { it.measuredWidth }.reduce { acc, i -> acc + i }, MeasureSpec.getSize(heightMeasureSpec))
            }
            hMode == MeasureSpec.AT_MOST -> {
                setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), children.map { it.measuredHeight }.max() ?: 0)
            }
        }
    }

    private fun layoutVertical() {
        var currentHeight = measuredHeight - padding
        children.forEach { child ->
            child.layout((measuredWidth - child.measuredWidth) / 2, currentHeight - child.measuredHeight, (measuredWidth + child.measuredWidth) / 2, currentHeight)
            currentHeight -= (child.measuredHeight + gap)
        }
    }

    private fun layoutHorizontal() {
        var currentRight = measuredWidth - padding
        children.forEach { child ->
            child.layout(currentRight - child.measuredWidth, (measuredHeight - child.measuredHeight)/2, currentRight, (measuredHeight + child.measuredHeight)/2)
            currentRight -= (child.measuredWidth + gap)
        }
    }
}